/**
  ******************************************************************************
  * @file    kea128_gpio.c
  * @author  花溪村长
  * @version V1.0
  * @date    18-8-2015
  * @brief   This file contains all the functions prototypes for the GPIO 
  *          firmware library.
  ******************************************************************************
**/ 
#include "kea128_gpio.h"
/***********************************************************************************************
 功能：GPIO初始化
 形参：GPIOx:
			 @arg PTA:A端口
			 @arg PTB:B端口
			 @arg PTC:C端口
			 @arg PTD:D端口
			 @arg PTE:E端口
			 @arg PTF:F端口
			 @arg PTG:G端口
			 @arg PTH:H端口
			 @arg PTI:I端口
			 GPIO_InitStruct
       GPIO 初始化结构
************************************************************************************************/
void GPIO_Init(GPIO_InitTypeDef* GPIO_InitStructure)
{
	GPIO_Type *GPIOx;
	uint16_t port;
	ASSERT((IS_GET_PORT(GPIO_InitStructure->GPIOx)));
	ASSERT(IS_GPIO_MODE(GPIO_InitStructure->GPIO_Mode));
	ASSERT(IS_GPIO_PIN(GPIO_InitStructure->GPIO_Pin));
	
	//判断GPIO口
	if(GPIO_InitStructure->GPIOx < PTE)
	{
		GPIOx = GPIOA;
		port = 8 * GPIO_InitStructure->GPIOx ;
	}
	else if(PTD<GPIO_InitStructure->GPIOx &&GPIO_InitStructure->GPIOx < PTI)
	{
		GPIOx = GPIOB;
		port = 8 * (GPIO_InitStructure->GPIOx-4) ;
	}
	else 
	{
		GPIOx = GPIOC;
		port = 8 * (GPIO_InitStructure->GPIOx-8) ;
	}
	
 //输出
	if(GPIO_InitStructure->GPIO_Mode == GPIO_Mode_OUT ) 
	{
		//设置输出模式
    GPIOx->PDDR &= ~(GPIO_InitStructure->GPIO_Pin << port);
		GPIOx->PDDR |= GPIO_InitStructure->GPIO_Pin << port;
		if(GPIO_InitStructure->GPIO_InitState == Bit_SET)
		 {
			  //设置高电平输出
			  GPIOx->PSOR &= ~(GPIO_InitStructure->GPIO_Pin << port);
				GPIOx->PSOR |= GPIO_InitStructure->GPIO_Pin << port;
		 }
		 else 
		 {
			 //设置低电平输出
			 GPIOx->PCOR &= ~(GPIO_InitStructure->GPIO_Pin << port);
			 GPIOx->PCOR |= GPIO_InitStructure->GPIO_Pin << port;
		 }
}
	//输出
	else
	{
		GPIOx->PDDR &= ~(GPIO_InitStructure->GPIO_Pin << port);   //输入
		GPIOx->PIDR &= ~(GPIO_InitStructure->GPIO_Pin << port); //允许输入	
		if(GPIO_InitStructure->GPIO_Mode == GPIO_Mode_IPU) //上拉
		 {
			 if(GPIOx==GPIOA)
			 {
				 PORT->PUE0 = (GPIO_InitStructure->GPIO_Pin << port);
			 }
			 else if(GPIOx==GPIOB)
			 {
				 PORT->PUE1 = (GPIO_InitStructure->GPIO_Pin << port);
			 }
			 else 
				 PORT->PUE2 = (GPIO_InitStructure->GPIO_Pin << port);
	    }
	}
}
/***********************************************************************************************
 功能: I/O电平翻转
 形参：GPIOx:
			 @arg PTA:A端口
			 @arg PTB:B端口
			 @arg PTC:C端口
			 @arg PTD:D端口
			 @arg PTE:E端口
			 @arg PTF:F端口
			 @arg PTG:G端口
			 @arg PTH:H端口
			 @arg PTI:I端口
		 	 GPIO_Pin：
			 @arg : PTA0-PI7
 返回：0
 详解：0
************************************************************************************************/
void GPIO_ToggleBit(uint16_t GPIOn,uint16_t GPIO_Pin)
{
	GPIO_Type *GPIOx;
	uint16_t port;
	ASSERT((IS_GET_PORT(GPIOx)));
	ASSERT(IS_GPIO_PIN(GPIO_Pin));
	//判断GPIO口
	if(GPIOn < PTE)
	{
		GPIOx = GPIOA;
		port = 8 * GPIOn ;
	}
	else if(PTD<GPIOn &&GPIOn < PTI)
	{
		GPIOx = GPIOB;
		port = 8 * (GPIOn-4) ;
	}
	else 
	{
		GPIOx = GPIOC;
		port = 8 * (GPIOn-8) ;
	}
	GPIOx->PTOR &= ~(GPIO_Pin<<port);
	GPIOx->PTOR |= (GPIO_Pin<<port);
}


/***********************************************************************************************
 功能: I/O输出高电平
 形参：GPIOx:
			 @arg PTA:A端口
			 @arg PTB:B端口
			 @arg PTC:C端口
			 @arg PTD:D端口
			 @arg PTE:E端口
			 @arg PTF:F端口
			 @arg PTG:G端口
			 @arg PTH:H端口
			 @arg PTI:I端口
		 	 GPIO_Pin：
			 @arg : PTA0-PI7
 返回：0
 详解：0
************************************************************************************************/
void GPIO_SetBits(uint16_t GPIOn, uint16_t GPIO_Pin)
{
	GPIO_Type *GPIOx;
	uint16_t port;
	ASSERT((IS_GET_PORT(GPIOx)));
	ASSERT(IS_GPIO_PIN(GPIO_Pin));
	//判断GPIO口
	if(GPIOn < PTE)
	{
		GPIOx = GPIOA;
		port = 8 * GPIOn ;
	}
	else if(PTD<GPIOn &&GPIOn < PTI)
	{
		GPIOx = GPIOB;
		port = 8 * (GPIOn-4) ;
	}
	else 
	{
		GPIOx = GPIOC;
		port = 8 * (GPIOn-8) ;
	}
	  GPIOx->PSOR &= ~(GPIO_Pin<<port);
	  GPIOx->PSOR |= (GPIO_Pin<<port);
}

/***********************************************************************************************
 功能: I/O输出低电平
 形参：GPIOx:
			 @arg PTA:A端口
			 @arg PTB:B端口
			 @arg PTC:C端口
			 @arg PTD:D端口
			 @arg PTE:E端口
			 @arg PTF:F端口
			 @arg PTG:G端口
			 @arg PTH:H端口
			 @arg PTI:I端口
		 	 GPIO_Pin：
			 @arg : PTA0-PI7
 返回：0
 详解：0
************************************************************************************************/
void GPIO_ResetBits(uint16_t GPIOn, uint16_t GPIO_Pin)
{
	GPIO_Type *GPIOx;
	uint16_t port;
	ASSERT((IS_GET_PORT(GPIOx)));
	ASSERT(IS_GPIO_PIN(GPIO_Pin));
	//判断GPIO口
	if(GPIOn < PTE)
	{
		GPIOx = GPIOA;
		port = 8 * GPIOn ;
	}
	else if(PTD<GPIOn &&GPIOn < PTI)
	{
		GPIOx = GPIOB;
		port = 8 * (GPIOn-4) ;
	}
	else 
	{
		GPIOx = GPIOC;
		port = 8 * (GPIOn-8) ;
	}
	  GPIOx->PCOR &= ~(GPIO_Pin<<port);
	  GPIOx->PCOR |= (GPIO_Pin<<port);
}

/***********************************************************************************************
 功能: PT端口数据
 形参：GPIOx:
			 @arg PTA:A端口
			 @arg PTB:B端口
			 @arg PTC:C端口
			 @arg PTD:D端口
			 @arg PTE:E端口
			 @arg PTF:F端口
			 @arg PTG:G端口
			 @arg PTH:H端口
			 @arg PTI:I端口
			 GPIO_Pin:
       起始端口
			 @arg : PTA0-PI0
       PortVal:
       端口数据
 返回：0
 详解：0
************************************************************************************************/
void GPIO_Write(uint16_t GPIOn,uint32_t PortVal)
{
	GPIO_Type *GPIOx;
	uint16_t port;
	ASSERT((IS_GET_PORT(GPIOx)));
	ASSERT(IS_GPIO_PIN(GPIO_Pin));
	//判断GPIO口
	if(GPIOn < PTE)
	{
		GPIOx = GPIOA;
		port = 8 * GPIOn ;
	}
	else if(PTD<GPIOn &&GPIOn < PTI)
	{
		GPIOx = GPIOB;
		port = 8 * (GPIOn-4) ;
	}
	else 
	{
		GPIOx = GPIOC;
		port = 8 * (GPIOn-8) ;
	}
	GPIOx->PDOR = (PortVal<<port);
}

/***********************************************************************************************
 功能：读取一个已经设置为输出的IO Pin的 电平
 形参：GPIOx:
			 @arg PTA:A端口
			 @arg PTB:B端口
			 @arg PTC:C端口
			 @arg PTD:D端口
			 @arg PTE:E端口
			 @arg PTF:F端口
			 @arg PTG:G端口
			 @arg PTH:H端口
			 @arg PTI:I端口
		 	 GPIO_Pin：
			 @arg : PTA0-PTI7
 返回：端口电平
 详解：实际上就是读取PDOR的值
************************************************************************************************/
uint8_t GPIO_ReadOutputDataBit(uint16_t GPIOn, uint16_t GPIO_Pin)
{
	uint8_t bitstatus = 0x00;
	uint32_t Pin = 0x00000000;
	GPIO_Type *GPIOx;
	uint16_t port;
	ASSERT((IS_GET_PORT(GPIOx)));
	ASSERT(IS_GPIO_PIN(GPIO_Pin));
	//判断GPIO口
	if(GPIOn < PTE)
	{
		GPIOx = GPIOA;
		port = 8 * GPIOn ;
	}
	else if(PTD<GPIOn &&GPIOn < PTI)
	{
		GPIOx = GPIOB;
		port = 8 * (GPIOn-4) ;
	}
	else 
	{
		GPIOx = GPIOC;
		port = 8 * (GPIOn-8) ;
	}
	  Pin |= GPIO_Pin<<port ;
    if((GPIOx->PDOR &(Pin) ) != (uint32_t)Bit_RESET)
    {
        bitstatus = (uint8_t)Bit_SET;
    }
    else
    {
        bitstatus = (uint8_t)Bit_RESET;
    }
    return bitstatus;
}
/***********************************************************************************************
功能：读取一个已经设置为输出的IO的 电平
形参：GPIOx:
			 @arg PTA:A端口
			 @arg PTB:B端口
			 @arg PTC:C端口
			 @arg PTD:D端口
			 @arg PTE:E端口
			 @arg PTF:F端口
			 @arg PTG:G端口
			 @arg PTH:H端口
			 @arg PTI:I端口
		 	 GPIO_Pin：
			 @arg : PTA0-PTI0
 返回：端口电平
 详解：实际上就是读取PDOR的值
************************************************************************************************/
uint32_t GPIO_ReadOutputData(uint16_t GPIOn,uint16_t GPIO_Pin)
{
	
  GPIO_Type *GPIOx;
	uint16_t port;
	ASSERT((IS_GET_PORT(GPIOx)));
	ASSERT(IS_GPIO_PIN(GPIO_Pin));
	//判断GPIO口
	if(GPIOn < PTE)
	{
		GPIOx = GPIOA;
		port = 8 * GPIOn ;
	}
	else if(PTD<GPIOn &&GPIOn < PTI)
	{
		GPIOx = GPIOB;
		port = 8 * (GPIOn-4) ;
	}
	else 
	{
		GPIOx = GPIOC;
		port = 8 * (GPIOn-8) ;
	}
  return (GPIOx->PDOR>>port );
}
/***********************************************************************************************
 功能：读取一个IO端口的某一个PIN的电平
 形参：GPIOx:
			 @arg PTA:A端口
			 @arg PTB:B端口
			 @arg PTC:C端口
			 @arg PTD:D端口
			 @arg PTE:E端口
			 @arg PTF:F端口
			 @arg PTG:G端口
			 @arg PTH:H端口
			 @arg PTI:I端口
		 	 GPIO_Pin：
			 @arg : PTA0-PTI7
 返回：逻辑电平 0 或者 1
 详解：必须先设置端口为输入端口
************************************************************************************************/
uint8_t GPIO_ReadInputDataBit(uint16_t GPIOn, uint16_t GPIO_Pin)
{	 
	uint8_t bitstatus = 0x00;
	uint32_t Pin = 0x00000000;
	GPIO_Type *GPIOx;
	uint16_t port;
	ASSERT((IS_GET_PORT(GPIOx)));
	ASSERT(IS_GPIO_PIN(GPIO_Pin));
	//判断GPIO口
	if(GPIOn < PTE)
	{
		GPIOx = GPIOA;
		port = 8 * GPIOn ;
	}
	else if(PTD<GPIOn &&GPIOn < PTI)
	{
		GPIOx = GPIOB;
		port = 8 * (GPIOn-4) ;
	}
	else 
	{
		GPIOx = GPIOC;
		port = 8 * (GPIOn-8) ;
	}
	  Pin |= GPIO_Pin<<port ;
    if((GPIOx->PDIR &(Pin) ) != (uint32_t)Bit_RESET)
    {
        bitstatus = (uint8_t)Bit_SET;
    }
    else
    {
        bitstatus = (uint8_t)Bit_RESET;
    }
    return bitstatus;
}
/***********************************************************************************************
 功能：读取一个IO端口的输入电平
 形参：GPIOx:
			 @arg PTA:A端口
			 @arg PTB:B端口
			 @arg PTC:C端口
			 @arg PTD:D端口
			 @arg PTE:E端口
			 @arg PTF:F端口
			 @arg PTG:G端口
			 @arg PTH:H端口
			 @arg PTI:I端口
		 	 GPIO_Pin：
			 @arg : PTA0-PTI0
 返回：端口电平
 详解：必须先设置端口为输入端口
************************************************************************************************/
uint32_t GPIO_ReadInputData(uint16_t GPIOn, uint16_t GPIO_Pin)
{
  GPIO_Type *GPIOx;
	uint16_t port;
	ASSERT((IS_GET_PORT(GPIOx)));
	ASSERT(IS_GPIO_PIN(GPIO_Pin));
	//判断GPIO口
	if(GPIOn < PTE)
	{
		GPIOx = GPIOA;
		port = 8 * GPIOn ;
	}
	else if(PTD<GPIOn &&GPIOn < PTI)
	{
		GPIOx = GPIOB;
		port = 8 * (GPIOn-4) ;
	}
	else 
	{
		GPIOx = GPIOC;
		port = 8 * (GPIOn-8) ;
	}
  return (GPIOx->PDIR>>port );
}
